home *** CD-ROM | disk | FTP | other *** search
/ MacHack 1997 / MacHack 1997.toast / Hacks / Hacks ’93 / OK, What was that again? / Extension / Backup / OSUtilsSup.c < prev   
Text File  |  1992-06-18  |  6KB  |  236 lines

  1.  
  2. /**************************************************************************************
  3.  
  4. FILENAME
  5.     OSUtilsSup.c
  6.  
  7. DESCRIPTION
  8.     A colection of utilities to aid in the patching of traps.
  9.     
  10. COPYRIGHT
  11.     Copyright © Apple Computer, Inc. 1990
  12.     All rights reserved.
  13.     
  14. ROUTINES
  15.     EXTERNAL
  16.         PatchTrap
  17.         RestoreTrap
  18.  
  19. MODIFICATION HISTORY
  20.     01/05/90    Sean Parent
  21.         1)    Ported from OpSysUtilSup.p and updated with lots of new wizzies.
  22.     03/04/90    sp
  23.         1)    Moved into Pack2.
  24.         2)    Added check for System 7.0.
  25.  
  26. **************************************************************************************/
  27.  
  28. #pragma segment Utilities
  29. #define            Pack2Internal
  30.  
  31. /**************************************************************************************
  32.  
  33. INCLUDES
  34.  
  35. **************************************************************************************/
  36.  
  37. #ifndef        __TYPES__
  38. #include    <Types.h>
  39. #endif
  40.  
  41. #ifndef        __MEMORY__
  42. #include    <Memory.h>
  43. #endif
  44.  
  45. #ifndef        __ERRORS__
  46. #include    <Errors.h>
  47. #endif
  48.  
  49. #ifndef        __TRAPS__
  50. #include    <Traps.h>
  51. #endif
  52.  
  53. #ifndef        __OSUTILS__
  54. #include    <OSUtils.h>
  55. #endif
  56.  
  57. #include "OSUtilsSup.h"
  58.  
  59. /*<FF>*/
  60. /**************************************************************************************
  61.  
  62. TYPEDEFS
  63.  
  64. **************************************************************************************/
  65.  
  66.  
  67. short NumToolboxTraps(void)
  68. {
  69.     if (GetToolboxTrapAddress(_InitGraf) == GetToolboxTrapAddress(0xAA6E)) {
  70.         return 0x0200;
  71.     } else return 0x0400;
  72. }
  73.  
  74. TrapType GetTrapType(short theTrap)
  75. {
  76.     enum { trapMask = 0x0800 };
  77.     
  78.     if (theTrap & trapMask) return ToolTrap;
  79.     else return OSTrap;
  80. }
  81.  
  82. Boolean TrapEntryAvailable(short theTrap, TrapType tType)
  83. {
  84.     /* Note: What about autopop? */
  85.  
  86.     if ((tType == ToolTrap) && ((theTrap & 0x03FF) >= NumToolboxTraps())) return false;
  87.     
  88.     #ifdef oldSupport
  89.     
  90.     /* Is the trap in part of the table that maybe overlayed? */
  91.     
  92.     if (((tType == ToolTrap) && ((theTrap & 0x03FF) < 0x0100)) || (tType == OSTrap)) {
  93.         long address = GetTrapAddress(theTrap, trapType);
  94.         
  95.         /* Is the trap table overlayed or are the traps duplicates and not unimplemented? */
  96.         
  97.         if ((GetToolboxTrapAddress(0xA000) == GetOSTrapAddress(0xA800))
  98.                 || ((address == NGetTrapAddress(theTrap, !trapType))
  99.                 && (address != GetToolboxTrapAddress(_Unimplemented)))) {
  100.         
  101.             /* Is it a valid trap type */
  102.         
  103.             theTrap &= 0x00FF;
  104.             if (((theTrap < 0x0050) || (theTrap == 0x0054) || (theTrap == 0x0057))
  105.                     != (tType == OSTrap)) return false;
  106.         }
  107.     }
  108.     #endif
  109.     
  110.     return true;
  111. }
  112.  
  113. Boolean TrapAvailable(short theTrap)
  114. {
  115.     TrapType tType;
  116.     
  117.     tType = GetTrapType(theTrap);
  118.     if (!TrapEntryAvailable(theTrap, tType)) return false;
  119.     return NGetTrapAddress(theTrap, tType) != GetToolboxTrapAddress(_Unimplemented);
  120. }
  121.  
  122. void FlushInstructionRange(void* address, long count)
  123. {
  124.     #pragma unused (address, count)
  125.  
  126.     FlushInstructionCache();
  127.  
  128.     #if false
  129.     if (TrapAvailable(_HWPriv)) {
  130.         if (FlushCodeCacheRange(address, count) == hwParamErr) {
  131.             FlushInstructionCache();
  132.         }
  133.     } else if (TrapAvailable(_FlushCodeCache)) FlushCodeCache();
  134.     #endif
  135. }
  136.  
  137. /*<FF>*/
  138. /**************************************************************************************
  139.  
  140. ROUTINE
  141.     PatchTrap
  142.  
  143. DESCRIPTION
  144.     Given a trap number and a routine address install a patch. If there is no entry in
  145.     the trap table for trap type (older machine) then return nil. The patchType may be
  146.     override and/or removable. If the patch is an override then nil will be returned if
  147.     the routine is already implemented (This is useful to avoid patching a trap twice).
  148.     If the patch is removeable then a reference will be returned to a block that is used
  149.     to unhook the patch on removal. The address of the previouse routine is returned
  150.     in oldRoutine or nil if it was unimplemented.
  151.  
  152. **************************************************************************************/
  153.  
  154. #define require(assertion, handler)         \
  155.     do {                                    \
  156.         if (assertion) ; else goto handler;    \
  157.     } while (false)
  158.     
  159.  
  160. #define JMP 0x4EF9
  161.  
  162. Patch PatchTrap(    ProcPtr*    oldRoutine,
  163.                     short        theTrap,
  164.                     ProcPtr        routine,
  165.                     PatchType    patchType)
  166. {
  167.     ProcPtr    tempRoutine;
  168.     TrapType tType;
  169.  
  170.     tType = GetTrapType(theTrap);
  171.     require(TrapEntryAvailable(theTrap, tType), TrapEntryAvailable);
  172.     
  173.     tempRoutine = (ProcPtr)NGetTrapAddress(theTrap, tType);
  174.     
  175.     if (oldRoutine) *oldRoutine = tempRoutine;
  176.     
  177.     if (*oldRoutine == NGetTrapAddress(_Unimplemented, ToolTrap)) {
  178.         *oldRoutine = nil;
  179.     }
  180.     
  181.     require(!((patchType & patchOverride) && *oldRoutine), TrapImplemented);
  182.     
  183.     if (patchType & patchRemovable) {
  184.         SPatch* patch = (SPatch*)NewPtrSys(sizeof(SPatch));
  185.         
  186.         require(patch, NewSysPtr);
  187.             
  188.         patch->jump        = JMP;
  189.         patch->where    = routine;
  190.         patch->trap        = theTrap;
  191.         patch->routine    = *oldRoutine;
  192.         
  193.         FlushInstructionRange(patch, sizeof(SPatch));
  194.         
  195.         NSetTrapAddress((long)patch, theTrap, tType);
  196.         return (Patch)patch;
  197.     } else {
  198.         NSetTrapAddress((long)routine, theTrap, tType);
  199.         return (Patch)-1;
  200.     }
  201.  
  202. NewSysPtr:
  203. TrapImplemented:
  204. TrapEntryAvailable:
  205.     return nil;
  206. }
  207.  
  208. /*<FF>*/
  209. /**************************************************************************************
  210.  
  211. ROUTINE
  212.     RestoreTrap
  213.  
  214. DESCRIPTION
  215.     Given a patch as returned by PatchTrap, RestoreTrap will remove the patch.
  216.  
  217. **************************************************************************************/
  218.  
  219. void RestoreTrap(Patch patch)
  220.     TrapType trapType = GetTrapType(patch->trap);
  221.         
  222.     /*
  223.         If the trap has been patched then change the jump vector to point to the
  224.         original routine. Otherwise set the trap address to point to the original
  225.         routine and dispose of the patch.
  226.     */
  227.     
  228.     if (NGetTrapAddress(((SPatch*)patch)->trap, trapType) != patch) {
  229.         ((SPatch*)patch)->where = ((SPatch*)patch)->routine;
  230.         FlushInstructionRange(patch, sizeof(SPatch));
  231.     } else {
  232.         NSetTrapAddress((long)patch->routine, ((SPatch*)patch)->trap, trapType);
  233.         DisposePtr((Ptr)patch);
  234.     }
  235. }